﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace WP7Contrib.View.Controls
{
  /// <summary>
  /// Renders a loading indicator whilst the content is being added to the visual tree. This
  /// results in an overall faster page load time.
  /// </summary>
  /// <remarks>
  /// <para>The hardware capabilities of WP7 devices mean that constructing complex UIs can 
  /// be a time consuming process. If you have a page that contains a large number of elements
  /// or the construction of these element requires complex calculations, it can take
  /// a long time before the page is loaded.
  /// </para>
  /// <para>The <c>DeferredLoadContentControl</c> improves initial page load times by rendering
  /// a simple loading UI which is displayed while the more complex UI is being constructed.
  /// </para>
  /// <para>see: <a href="http://www.scottlogic.co.uk/blog/colin/2011/01/windows-phone-7-deferredloadcontentcontrol/">Windows Phone 7 DeferredLoadContentControl</a></para>
  /// </remarks>
  public class DeferredLoadContentControl : ContentControl
  {
    private ContentPresenter _contentPresenter;

    private FrameworkElement _loadingIndicator;

    private bool _loaded = false;

    public DeferredLoadContentControl()
    {
      this.DefaultStyleKey = typeof(DeferredLoadContentControl);

      if (!DesignerProperties.IsInDesignTool)
      {
        this.Loaded += DeferredLoadContentControl_Loaded;
      }
    }

    public override void OnApplyTemplate()
    {
      base.OnApplyTemplate();

      _contentPresenter = this.GetTemplateChild("contentPresenter") as ContentPresenter;
      _loadingIndicator = this.GetTemplateChild("loadingIndicator") as FrameworkElement;

      if (DesignerProperties.IsInDesignTool)
      {
        _contentPresenter.Visibility = Visibility.Visible;

        // in design-mode show the contents 'grayed out'
        _contentPresenter.Opacity = 0.5;
      }

      if (_loaded)
      {
        LoadContent();
      }
    }

    private void LoadContent()
    {
      Dispatcher.BeginInvoke(() =>
        {
          _contentPresenter.Visibility = Visibility.Visible;
          _contentPresenter.LayoutUpdated += ContentPresenter_LayoutUpdated;
        });
    }

    private void DeferredLoadContentControl_Loaded(object sender, RoutedEventArgs e)
    {
      _loaded = true;

      // content has loaded, now show our content presenter
      if (_contentPresenter != null)
      {
        LoadContent();
      }
    }

    private void ContentPresenter_LayoutUpdated(object sender, EventArgs e)
    {
      // the content presenter has been rendered, hide the loading indicator
      _contentPresenter.LayoutUpdated -= ContentPresenter_LayoutUpdated;
      _loadingIndicator.Visibility = Visibility.Collapsed;
    }
  }
}
